/**
 * 2024/01/01 - 2024/12/31
 **/
package com.snail.camunda.engin.process.manager;

import com.snail.camunda.engin.process.dto.DeleteProcessDTO;
import com.snail.camunda.engin.process.dto.DoneDTO;
import com.snail.camunda.engin.process.dto.ProcessDeployDTO;
import com.snail.camunda.engin.process.dto.TodoDTO;
import com.snail.camunda.engin.process.holder.HistoryHolder;
import com.snail.camunda.engin.process.holder.RuntimeHolder;
import com.snail.camunda.engin.process.holder.TaskHolder;
import com.snail.camunda.engin.process.mapping.HistoryMapping;
import com.snail.camunda.engin.process.vo.DoneVO;
import com.snail.camunda.engin.process.vo.HistoryActivityVO;
import com.snail.camunda.engin.process.vo.TodoVO;
import com.snail.start.utils.lambda.GenericEntityBuilder;
import com.snail.start.utils.threadlocal.UserContextUtils;
import com.snail.starter.commons.page.PageQO;
import com.snail.starter.commons.page.PageVO;
import org.camunda.bpm.engine.RepositoryService;
import org.camunda.bpm.engine.history.HistoricTaskInstance;
import org.camunda.bpm.engine.repository.Deployment;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author: (zg)
 * @Date: 2024/12/12 13:22
 * @Version: 1.0.0
 */
@Component
public class ProcessManager {

    @Resource
    RepositoryService repositoryService;

    @Resource
    HistoryHolder historyHolder;

    @Resource
    TaskHolder taskHolder;

    @Resource
    RuntimeHolder runtimeHolder;

    @Resource
    HistoryMapping historyMapping;

    public String deploy(ProcessDeployDTO processDeploy) {
        Deployment deploy = repositoryService.createDeployment()
                .name(processDeploy.getName())
                .tenantId(UserContextUtils.get().getTenantId().toString())
                .addClasspathResource(processDeploy.getBpmFileName())
                .deploy();
        return deploy.getId();
    }

    public String start(String processId) {
        return runtimeHolder.startProcessInstanceById(processId);
    }

    public boolean stop(String processId, DeleteProcessDTO deleteProcess) {
        return runtimeHolder.deleteProcessInstance(processId, deleteProcess.getDeleteReason());
    }

    public PageVO<TodoVO> todo(PageQO<TodoDTO> page) {
        return taskHolder.page(page, task -> GenericEntityBuilder.of(TodoVO::new)
                .with(TodoVO::setTenantId, task.getTenantId())
                .with(TodoVO::setParentTaskId, task.getParentTaskId())
                .with(TodoVO::setProcessInstanceId, task.getProcessInstanceId())
                .with(TodoVO::setAssignee, task.getAssignee())
                .with(TodoVO::setOwner, task.getOwner())
                .with(TodoVO::setName, task.getName())
                .with(TodoVO::setDescription, runtimeHolder.getVariableString(task.getExecutionId(), "title"))
                .with(TodoVO::setDueDate, task.getDueDate())
                .with(TodoVO::setFollowUpDate, task.getFollowUpDate())
                .with(TodoVO::setPriority, task.getPriority())
                .with(TodoVO::setTaskDefinitionKey, task.getTaskDefinitionKey())
                .build());
    }

    public PageVO<DoneVO> done(PageQO<DoneDTO> page) {
        return historyHolder.page(page, historicTaskInstance -> GenericEntityBuilder.of(DoneVO::new)
                .with(DoneVO::setTenantId, historicTaskInstance.getTenantId())
                .with(DoneVO::setParentTaskId, historicTaskInstance.getParentTaskId())
                .with(DoneVO::setProcessInstanceId, historicTaskInstance.getProcessInstanceId())
                .with(DoneVO::setAssignee, historicTaskInstance.getAssignee())
                .with(DoneVO::setOwner, historicTaskInstance.getOwner())
                .with(DoneVO::setName, historicTaskInstance.getName())
                .with(DoneVO::setDescription, runtimeHolder.getVariableString(historicTaskInstance.getExecutionId(), "title"))
                .with(DoneVO::setDueDate, historicTaskInstance.getDueDate())
                .with(DoneVO::setFollowUpDate, historicTaskInstance.getFollowUpDate())
                .with(DoneVO::setPriority, historicTaskInstance.getPriority())
                .with(DoneVO::setDeleteReason, historicTaskInstance.getDeleteReason())
                .with(DoneVO::setTaskDefinitionKey, historicTaskInstance.getTaskDefinitionKey())
                .with(DoneVO::setActivityInstanceId, historicTaskInstance.getActivityInstanceId())
                .with(DoneVO::setStartTime, historicTaskInstance.getStartTime())
                .with(DoneVO::setDurationInMillis, historicTaskInstance.getDurationInMillis())
                .with(DoneVO::setEndTime, historicTaskInstance.getEndTime())
                .build());
    }

    public List<HistoryActivityVO> history(String processInstanceId) {
        List<HistoricTaskInstance> historicTaskInstances = historyHolder.history(processInstanceId);
        if (null == historicTaskInstances || historicTaskInstances.isEmpty()) {
            return new ArrayList<>();
        }
        return historicTaskInstances.stream().map(historyMapping::historyTOVo).collect(Collectors.toList());
    }
}